package org.example.service.workItem.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.example.mapper.WorkItemMapper;
import org.example.model.common.AppHttpCodeEnum;
import org.example.model.common.PageResponseDto;
import org.example.model.common.ResponseResult;
import org.example.model.user.dtos.UserIdentityDto;
import org.example.model.workItem.dtos.WorkItemDto;
import org.example.model.workItem.entities.WorkItem;
import org.example.model.workItem.vos.ModifyWorkItemVo;
import org.example.model.workItem.vos.SearchWorkItemVo;
import org.example.service.workItem.WorkItemService;
import org.example.utils.DataExchangeUtils;
import org.example.utils.UserIdThreadLocalUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;

/**
 * 工作项服务层实现
 */
@Service
@Transactional
@Slf4j
public class WorkItemServiceImpl extends ServiceImpl<WorkItemMapper, WorkItem> implements WorkItemService {

    @Autowired
    private WorkItemMapper workItemMapper;

    /**
     * 添加一条工作项
     */
    @Override
    public ResponseResult<Boolean> InsertWorkItem(ModifyWorkItemVo modifyWorkItemVo) {
        ResponseResult<Boolean> result = new ResponseResult<>();
        // 参数审查
        if (modifyWorkItemVo == null) {
            // 缺少参数
            result.error(AppHttpCodeEnum.PARAM_REQUIRE.getCode(), AppHttpCodeEnum.PARAM_REQUIRE.getErrorMessage());
            return result;
        }
        WorkItem workItem = new WorkItem();
        BeanUtils.copyProperties(modifyWorkItemVo, workItem);
        this.HandleWorkItemBasic(workItem);
        Boolean flag = workItemMapper.insert(workItem) > 0;
        result.ok(AppHttpCodeEnum.SUCCESS.getCode(), flag, AppHttpCodeEnum.SUCCESS.getErrorMessage());
        return result;
    }

    //处理添加工作项信息时共有信息的处理
    private void HandleWorkItemBasic (WorkItem workItem) {
        if (workItem.getType() == 1) {
            if (workItem.getTaskStatus() == 1) {
                workItem.setStartTime(LocalDateTime.now());
            } else if (workItem.getTaskStatus() == 2) {
                workItem.setEndTime(LocalDateTime.now());
            }
        }
        // 获取进程中的用户数据
        UserIdentityDto userIdentityDto = UserIdThreadLocalUtils.getUser();
        if (workItem.getId() == 0) {
            workItem.setCreateUserId(userIdentityDto.getId());
            workItem.setCreateTime(LocalDateTime.now());
            workItem.setIsDeleted(false);
        }
        workItem.setUpdateUserId(userIdentityDto.getId());
        workItem.setUpdateTime(LocalDateTime.now());
    }

    /**
     * 根据id修改一条工作项
     */
    @Override
    public ResponseResult<Boolean> UpdateWorkItemById(ModifyWorkItemVo modifyWorkItemVo) {
        ResponseResult<Boolean> result = new ResponseResult<>();
        // 参数审查
        if (modifyWorkItemVo == null || modifyWorkItemVo.getId() <= 0) {
            // 缺少参数 工作项信息id
            result.error(AppHttpCodeEnum.PARAM_REQUIRE.getCode(), AppHttpCodeEnum.PARAM_REQUIRE.getErrorMessage());
            return result;
        }
        WorkItem workItem = workItemMapper.selectById(modifyWorkItemVo.getId());
        BeanUtils.copyProperties(modifyWorkItemVo, workItem);
        this.HandleWorkItemBasic(workItem);
        Boolean flag = workItemMapper.updateById(workItem) > 0;
        result.ok(AppHttpCodeEnum.SUCCESS.getCode(), flag, AppHttpCodeEnum.SUCCESS.getErrorMessage());
        return result;
    }

    /**
     * 根据id删除一条工作项
     */
    @Override
    public ResponseResult<Boolean> DeleteWorkItemById(Integer id) {
        ResponseResult<Boolean> result = new ResponseResult<>();
        // 参数审查
        if (id <= 0) {
            // 缺少参数 工作项信息id
            result.error(AppHttpCodeEnum.PARAM_REQUIRE.getCode(), AppHttpCodeEnum.PARAM_REQUIRE.getErrorMessage());
            return result;
        }
        WorkItem workItem = workItemMapper.selectById(id);
        workItem.setIsDeleted(true);
        this.HandleWorkItemBasic(workItem);
        Boolean flag = workItemMapper.updateById(workItem) > 0;
        result.ok(AppHttpCodeEnum.SUCCESS.getCode(), flag, AppHttpCodeEnum.SUCCESS.getErrorMessage());
        return result;
    }

    /**
     * 根据条件分页获取工作项列表
     */
    @Override
    public ResponseResult<PageResponseDto<List<WorkItemDto>>> SelectWorkItemByPage(SearchWorkItemVo searchWorkItemVo) {
        ResponseResult<PageResponseDto<List<WorkItemDto>>> result = new ResponseResult<>();
        // 参数审查
        if (searchWorkItemVo == null || searchWorkItemVo.getProjectId() == 0) {
            // 缺少参数
            result.error(AppHttpCodeEnum.PARAM_REQUIRE.getCode(), AppHttpCodeEnum.PARAM_REQUIRE.getErrorMessage());
            return result;
        }
        // 查询条件
        LambdaQueryWrapper<WorkItem> workItemQuery = new LambdaQueryWrapper<>();
        this.handleWorkItemCondition(workItemQuery, 0, searchWorkItemVo);
        // 分页查询
        IPage<WorkItem> workItemIPage = new Page<>(searchWorkItemVo.getPageIndex(), searchWorkItemVo.getPageSize());
        IPage<WorkItem> workItemListPage = workItemMapper.selectPage(workItemIPage, workItemQuery);
        PageResponseDto<List<WorkItemDto>> workItemPageDto = new PageResponseDto<>();
        workItemPageDto.setSize(workItemMapper.selectCount(workItemQuery).intValue());
        // 处理返回数据
        List<WorkItem> workItemList = workItemListPage.getRecords();
        List<WorkItemDto> workItemDtoList = new ArrayList<>();
        WorkItemDto workItemDto = null;
        for (WorkItem workItem : workItemList) {
            workItemDto = new WorkItemDto();
            BeanUtils.copyProperties(workItem, workItemDto);
            workItemDto = this.GetWorkItemDetail(workItemDto, searchWorkItemVo);
            workItemDtoList.add(workItemDto);
        }
        workItemPageDto.setData(workItemDtoList);
        result.ok(AppHttpCodeEnum.SUCCESS.getCode(), workItemPageDto, AppHttpCodeEnum.SUCCESS.getErrorMessage());
        return result;
    }

    // 查询条件处理
    private void handleWorkItemCondition(LambdaQueryWrapper<WorkItem> workItemQuery, int parentId, SearchWorkItemVo searchWorkItemVo) {
        workItemQuery.eq(WorkItem::getParentId, parentId)
                .eq(WorkItem::getIsDeleted, false)
                .eq(WorkItem::getProjectId, searchWorkItemVo.getProjectId())
                .orderByDesc(WorkItem::getRequirePriority)
                .orderByDesc(WorkItem::getTaskStatus)
                .orderByAsc(WorkItem::getCreateTime);
//                .or(workItem -> workItem
//                        .and(require -> require
//                                .eq(WorkItem::getType, 0)
//                                .like(StringUtils.isNotBlank(searchWorkItemVo.getRequireName()), WorkItem::getName, searchWorkItemVo.getRequireName())
//                                .eq(searchWorkItemVo.getRequirePriority() != null, WorkItem::getRequirePriority, searchWorkItemVo.getRequirePriority())
//                        )
//                        .or(task -> task
//                                .eq(WorkItem::getType, 1)
//                                .like(StringUtils.isNotBlank(searchWorkItemVo.getTaskName()), WorkItem::getName, searchWorkItemVo.getTaskName())
//                                .eq(searchWorkItemVo.getTaskStatus() != null, WorkItem::getTaskStatus, searchWorkItemVo.getTaskStatus())
//                        )
//                );
    }

    // 获取工作项详情
    private WorkItemDto GetWorkItemDetail(WorkItemDto workItemDto, SearchWorkItemVo searchWorkItemVo) {
        double taskDuration = 0;
        if (workItemDto.getStartTime() != null && workItemDto.getEndTime() != null) {
            taskDuration = this.calculateTaskDuration(workItemDto.getStartTime(), workItemDto.getEndTime());
            workItemDto.setTaskHours(taskDuration);
        }
        List<WorkItemDto> workItemDtoList = this.GetWorkItemChildList(workItemDto.getId(), searchWorkItemVo);
        if (workItemDtoList.size() == 0) {
            if (workItemDto.getType() == 0) workItemDto.setRequireStatus(0);
            return workItemDto;
        }
        int requireStatus;
        int notYetStartedCount = 0;
        int completedCount = 0;
        for (WorkItemDto tempWorkItem : workItemDtoList) {
            this.GetWorkItemDetail(tempWorkItem, searchWorkItemVo);
            if (tempWorkItem.getType() == 0) {
                if (tempWorkItem.getRequireStatus() == 0) {
                    notYetStartedCount++;
                } else if (tempWorkItem.getRequireStatus() == 2) {
                    completedCount++;
                }
            } else if (tempWorkItem.getType() == 1){
                if (tempWorkItem.getTaskStatus() == 0) {
                    notYetStartedCount ++;
                } else if (tempWorkItem.getTaskStatus() == 2) {
                    completedCount++;
                }
            }
            taskDuration += tempWorkItem.getTaskHours();
        }
        if (notYetStartedCount == workItemDtoList.size()) {
            requireStatus = 0;
        } else if (completedCount == workItemDtoList.size()) {
            requireStatus = 2;
        } else {
            requireStatus = 1;
        }
        if (workItemDto.getType() == 0) {
            workItemDto.setRequireStatus(requireStatus);
            taskDuration = DataExchangeUtils.DoubleRound(taskDuration ,2);
            workItemDto.setTaskHours(taskDuration);
        }
        workItemDto.setWorkItemDtos(workItemDtoList);
        return workItemDto;
    }

    //根据工作项父id获取符合条件子工作项列表
    private List<WorkItemDto> GetWorkItemChildList(int parentId, SearchWorkItemVo searchWorkItemVo){
        // 查询条件
        LambdaQueryWrapper<WorkItem> workItemQuery = new LambdaQueryWrapper<>();
        this.handleWorkItemCondition(workItemQuery, parentId, searchWorkItemVo);
        List<WorkItem> workItemList = workItemMapper.selectList(workItemQuery);
        List<WorkItemDto> workItemDtoList = new ArrayList<>();
        WorkItemDto workItemDto = null;
        for (WorkItem workItem : workItemList) {
            workItemDto = new WorkItemDto();
            BeanUtils.copyProperties(workItem, workItemDto);
            workItemDtoList.add(workItemDto);
        }
        return workItemDtoList;
    }

    // 计算任务时长
    private double calculateTaskDuration (LocalDateTime startTime, LocalDateTime endTime) {

        ZoneId zoneId = ZoneId.systemDefault();
        Instant startTimeInstant = startTime.atZone(zoneId).toInstant();
        long startTimeMin = startTimeInstant.toEpochMilli();
        Instant endTimeInstant = endTime.atZone(zoneId).toInstant();
        long endTimeMin = endTimeInstant.toEpochMilli();
        double differValue = 0;
        if (endTimeMin > startTimeMin) {
            long seconds = ChronoUnit.SECONDS.between(startTime, endTime);
            long hours = ChronoUnit.HOURS.between(startTime, endTime);
            if (hours > 13) {
                long days = ChronoUnit.DAYS.between(startTime.toLocalDate(), endTime.toLocalDate());
                seconds = seconds - days * 11 * 60 * 60;
            }
            differValue = ((double) seconds) / (60 * 60);
            differValue = DataExchangeUtils.DoubleRound(differValue ,2);
        }
        // 工作时间 上午8：00-晚上9：00
        return differValue;
    }


    /**
     * 根据项目id获取当前项目的总用时
     */
    @Override
    public double GetProjectTimeSpentByProjectId(Integer projectId) {
        double timeSpent = 0;
        LambdaQueryWrapper<WorkItem> workItemQuery = new LambdaQueryWrapper<>();
        workItemQuery.eq(WorkItem::getIsDeleted, false)
                .eq(WorkItem::getProjectId, projectId)
                .eq(WorkItem::getType, 1);
        List<WorkItem> workItemList = workItemMapper.selectList(workItemQuery);
        for (WorkItem workItem : workItemList) {
            if (workItem.getStartTime() != null && workItem.getEndTime() != null) {
                timeSpent += this.calculateTaskDuration(workItem.getStartTime(), workItem.getEndTime());
            }
        }
        timeSpent = DataExchangeUtils.DoubleRound(timeSpent ,2);
        return timeSpent;
    }
}
